package com.example.androidproject.online;

import android.content.Context;
import android.util.Log;

import com.example.androidproject.sqlite.FileRepository;

import java.io.*;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Client {
    private static final String TAG = "Client...";
    private static final int RECONNECT_DELAY_MS = 1000; // 1秒钟的重连延迟
    private Socket socket;
    private PrintWriter out;
    private DataInputStream dis;
    private final Context context;
    private volatile boolean isRunning = true; // 控制客户端是否继续运行
    private BlockingQueue<String> messageQueue = new LinkedBlockingQueue<>();
    private BlockingQueue<FileRepository.FileRecord> fileQueue = new LinkedBlockingQueue<>();
    private String serverAddress;
    private int port;

    public Client(Context context) {
        this.context = context;
    }

    public void start(String serverAddress, int port) {
        this.serverAddress = serverAddress;
        this.port = port;
        new Thread(() -> {
            while (isRunning) {
                try {
                    connect(serverAddress, port);// 持续处理消息接收
                    receiveMessages();
                } catch (IOException e) {
                    Log.e(TAG, "Connection failed: " + e.getMessage());
                }
                // 等待后再重连，以避免快速重连
                try {
                    Thread.sleep(RECONNECT_DELAY_MS);
                } catch (InterruptedException e) {
                    Log.e(TAG, "Reconnect delay interrupted: " + e.getMessage());
                    Thread.currentThread().interrupt(); // 恢复中断状态
                }
            }

        }).start();
    }

    private void connect(String serverAddress, int port) throws IOException {
        isRunning = true;
        if(socket == null ||socket.isClosed()){
            socket = new Socket(serverAddress, port);
            out = new PrintWriter(socket.getOutputStream(), true);
            dis = new DataInputStream(socket.getInputStream());
            Log.d(TAG, "Connection established successfully");
        }

    }

    private void receiveMessages() {
        Log.e(TAG, "receiveMessages: " );
        while (isRunning) {
            try {
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                String header = dis.readUTF(); // 读取头部信息
                if (header.startsWith("FILE_TRANSFER:")) {
                    receiveFile(header);
                } else {
                    handleMessage(header);
                }
            } catch (EOFException e) {
                Log.e(TAG, "End of stream reached: " + e.getMessage(), e);
                close();
                // 等待重连
                try {
                    Thread.sleep(RECONNECT_DELAY_MS);
                } catch (InterruptedException ie) {
                    Log.e(TAG, "Reconnect delay interrupted: " + ie.getMessage(), ie);
                    Thread.currentThread().interrupt(); // 恢复中断状态
                }
                try {
                    connect(serverAddress, port);
                } catch (IOException ioException) {
                    Log.e(TAG, "Reconnection failed: " + ioException.getMessage());
                }
            } catch (IOException e) {
                Log.e(TAG, "Error receiving messages: " + e.getMessage(), e);
                close();
                // 等待重连
                try {
                    Thread.sleep(RECONNECT_DELAY_MS);
                } catch (InterruptedException ie) {
                    Log.e(TAG, "Reconnect delay interrupted: " + ie.getMessage(), ie);
                    Thread.currentThread().interrupt(); // 恢复中断状态
                }
                try {
                    connect(serverAddress, port);
                } catch (IOException ioException) {
                    Log.e(TAG, "Reconnection failed: " + ioException.getMessage());
                }
            }
        }
    }

    private void receiveFile(String fileInfo) {
        try {
            // 从文件信息中提取文件名
            String fileName = fileInfo.substring("FILE_TRANSFER:".length());
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            long fileLength = dis.readLong();
            Log.d(TAG, "Receiving file: " + fileName + ", size: " + fileLength + " bytes");

            byte[] buffer = new byte[2 * 1024 * 1024]; // 2MB缓冲区
            File file = new File(context.getCacheDir(), fileName);
            try (FileOutputStream fos = new FileOutputStream(file)) {
                long bytesReceived = 0;
                while (bytesReceived < fileLength) {
                    int bytesToRead = (int) Math.min(buffer.length, fileLength - bytesReceived);
                    int read = dis.read(buffer, 0, bytesToRead);
                    if (read == -1) break; // End of stream
                    fos.write(buffer, 0, read);
                    bytesReceived += read;
                    Log.d(TAG, "Receiving file progress: " + (bytesReceived * 100 / fileLength) + "%");
                }
                Log.d(TAG, "File received and written to: " + file.getAbsolutePath());
            }
            fileQueue.offer(new FileRepository.FileRecord(fileName,System.currentTimeMillis(),serverAddress));
        } catch (IOException e) {
            Log.e(TAG, "Error receiving file: " + e.getMessage(), e);
        }
    }

    private void handleMessage(String message) {
        Log.d(TAG, "Received message: " + message);
        // 在这里处理接收到的文本消息
        messageQueue.offer(message);
    }


    public synchronized void sendMessage(String message) throws IOException {
        if (out != null) {
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            dos.writeUTF(message);
            dos.flush();
            Log.d(TAG, "Message sent: " + message);
        } else {
            Log.e(TAG, "PrintWriter is null. Unable to send message.");
        }
    }
    public synchronized void sendFile(File file) {
        Log.d(TAG, "Attempting to send file to client: " + file.length());
        try (FileInputStream fis = new FileInputStream(file);
             DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
            // 发送文件名
            dos.writeUTF("FILE_TRANSFER:" + file.getName());
            dos.flush();
            // 发送文件长度
            dos.writeLong(file.length());
            dos.flush();
            // 发送文件内容
            byte[] buffer = new byte[2 * 1024 * 1024]; // 2MB缓冲区
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                dos.write(buffer, 0, bytesRead);
            }
            dos.flush();
            Log.d(TAG, "File sent successfully to client: " + file.getName());
        } catch (IOException e) {
            Log.e(TAG, "Error sending file to client: " + e.getMessage());
        }
    }

    public void close() {
        isRunning = false;
        try {
            if (dis != null) dis.close();
            if (out != null) out.close();
            if (socket != null && !socket.isClosed()) socket.close();
        } catch (IOException e) {
            Log.e(TAG, "Error closing resources: " + e.getMessage());
        }
    }

    public String getNextMessage() {
        return messageQueue.poll();
    }
    public FileRepository.FileRecord getNextFile() {
        return fileQueue.poll();
    }
}
